package admin

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/go-playground/validator/v10"
	"github.com/labstack/echo/v4"
	"gorm.io/datatypes"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"techoiceness.com/aiagent/llm-gateway/internal/agent"
	"techoiceness.com/aiagent/llm-gateway/internal/auth"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
	"techoiceness.com/aiagent/llm-gateway/internal/llm"
	"techoiceness.com/aiagent/llm-gateway/internal/repository"
	"techoiceness.com/aiagent/llm-gateway/internal/server/response"
	"techoiceness.com/aiagent/llm-gateway/internal/tools"
)

// AdminHandler 管理端处理器
type AdminHandler struct {
	// 保留db字段用于向后兼容，逐步迁移到repository
	db *gorm.DB

	validator  *validator.Validate
	jwtManager *auth.JWTManager

	// Repository容器统一管理所有repository
	repos repository.ContainerInterface

	llmProviderManager *llm.ProviderManager
	toolManager        *tools.ToolManager
	agentHub           *agent.AgentHub
}

// NewAdminHandler 创建管理端处理器
func NewAdminHandler(
	jwtManager *auth.JWTManager,
	agentHub *agent.AgentHub,
	llmProviderManager *llm.ProviderManager,
	toolManager *tools.ToolManager,
	repos repository.ContainerInterface,
) *AdminHandler {
	return &AdminHandler{
		db:                 repos.GetDB(), // 向后兼容，用于逐步迁移
		validator:          validator.New(),
		jwtManager:         jwtManager,
		agentHub:           agentHub,
		repos:              repos,
		llmProviderManager: llmProviderManager,
		toolManager:        toolManager,
	}
}

// RegisterRoutes 注册管理端路由
func (h *AdminHandler) RegisterRoutes(e *echo.Group, authMiddleware *auth.AuthMiddleware, authEntityFactory func() auth.Authenticatable) {
	adminGroup := e.Group("/admin")

	// 管理员登录（无需认证）
	adminGroup.POST("/login", h.Login)

	// 需要认证的管理员路由
	protected := adminGroup.Group("", authMiddleware.JWT(authEntityFactory))
	{
		// 用户管理
		protected.GET("/users", h.GetUsers)
		protected.POST("/users", h.CreateUser)
		protected.GET("/users/:id", h.GetUserDetail)
		protected.PUT("/users/:id", h.UpdateUser)
		protected.DELETE("/users/:id", h.DeleteUser)
		protected.POST("/users/:id/reset-password", h.ResetUserPassword)

		// 获取对话列表
		protected.GET("/conversations", h.GetConversations)

		// 获取对话详情
		protected.GET("/conversations/:conversation_id", h.GetConversationDetail)

		// 获取LLM交互消息列表
		protected.GET("/llm-messages", h.GetLLMMessages)

		// 获取LLM消息详情（包含完整调试信息）
		protected.GET("/llm-messages/:id", h.GetLLMMessageDetail)

		// 获取客户端消息列表
		protected.GET("/client-messages", h.GetClientMessages)

		// 获取客户端消息详情
		protected.GET("/client-messages/:id", h.GetClientMessageDetail)

		// 获取系统提示词列表
		protected.GET("/system-prompts", h.GetSystemPrompts)

		// 创建系统提示词
		protected.POST("/system-prompts", h.CreateSystemPrompt)

		// 更新系统提示词
		protected.PUT("/system-prompts/:id", h.UpdateSystemPrompt)

		// 删除系统提示词
		protected.DELETE("/system-prompts/:id", h.DeleteSystemPrompt)

		// 获取仪表盘统计数据
		protected.GET("/dashboard/stats", h.GetDashboardStats)

		// LLM Provider 管理
		protected.GET("/llm-providers", h.GetLLMProviders)
		protected.POST("/llm-providers", h.CreateLLMProvider)
		protected.GET("/llm-providers/:id", h.GetLLMProvider)
		protected.PUT("/llm-providers/:id", h.UpdateLLMProvider)
		protected.DELETE("/llm-providers/:id", h.DeleteLLMProvider)
		protected.POST("/llm-providers/:id/default", h.SetLLMProviderDefault)
		protected.POST("/llm-providers/:id/toggle", h.SetLLMProviderEnabled)

		// 模型管理
		protected.GET("/llm-providers/:id/models", h.GetLLMProviderModels)
		protected.POST("/llm-providers/:id/models", h.AddModelToLLMProvider)
		protected.PUT("/llm-providers/:id/models/:model", h.UpdateLLMProviderModel)
		protected.DELETE("/llm-providers/:id/models/:model", h.DeleteLLMProviderModel)
		protected.POST("/llm-providers/:id/models/:model/toggle", h.SetLLMProviderModelDefault)

		// 工具管理
		protected.GET("/tools", h.ListTools)
		protected.POST("/tools/:name/execute", h.ExecuteTool)
		protected.GET("/tools/:name", h.GetTool)
		protected.PUT("/tools/:name", h.UpdateTool)
		protected.GET("/tools/:name/definition", h.GetToolDefinition)
		protected.PUT("/tools/:name/status", h.UpdateToolStatus)
		protected.POST("/tools/:name/test-connection", h.TestToolConnection)

		// 数据库架构管理
		protected.GET("/schema", h.GetDatabaseSchema)
		protected.GET("/schema/tables", h.GetTableList)
		protected.GET("/schema/table", h.GetTableSchema)

		// 工具数据库架构管理
		protected.GET("/tools/:tool_name/database-schema", h.GetToolDatabaseSchema)
	}
}

// ========== 工具管理相关方法 ==========

// UpdateToolRequest 更新工具请求
type UpdateToolRequest struct {
	DisplayName *string         `json:"display_name"`
	Description *string         `json:"description"`
	Category    *string         `json:"category"`
	Config      json.RawMessage `json:"config"` // 使用 RawMessage 来处理 null/object
}

// UpdateToolStatusRequest 更新工具状态请求
type UpdateToolStatusRequest struct {
	Name      string `param:"name" validate:"required"`
	IsEnabled bool   `json:"is_enabled" validate:"required"`
}

// ListTools 列出所有工具
func (h *AdminHandler) ListTools(c echo.Context) error {
	tools := h.toolManager.ListTools()

	toolList := make([]map[string]interface{}, len(tools))
	for i, tool := range tools {
		toolInfo := map[string]interface{}{
			"name":         tool.Name(),
			"display_name": tool.Name(),
			"description":  tool.Description(),
			"version":      "1.0.0",
			"category":     "builtin",
			"is_enabled":   h.toolManager.IsToolEnabled(tool.Name()),
			"usage_count":  0,
			"last_used_at": "",
			"created_at":   time.Now().Format(time.RFC3339),
			"updated_at":   time.Now().Format(time.RFC3339),
		}

		// 如果有数据库存储，获取统计信息
		if stats, err := h.toolManager.GetToolStats(tool.Name()); err == nil {
			toolInfo["id"] = stats.ID.String()
			toolInfo["display_name"] = stats.DisplayName
			toolInfo["description"] = stats.Description
			toolInfo["is_enabled"] = stats.IsEnabled
			toolInfo["usage_count"] = stats.UsageCount
			if stats.LastUsedAt != nil {
				toolInfo["last_used_at"] = stats.LastUsedAt.Format(time.RFC3339)
			}
			toolInfo["created_at"] = stats.CreatedAt.Format(time.RFC3339)
			toolInfo["updated_at"] = stats.UpdatedAt.Format(time.RFC3339)

			// 新增：返回config字段
			if stats.Config != nil {
				var configObj interface{}
				_ = json.Unmarshal([]byte(*stats.Config), &configObj)
				toolInfo["config"] = configObj
			} else {
				toolInfo["config"] = nil
			}
		}

		toolList[i] = toolInfo
	}

	return response.Success(c, toolList)
}

// GetTool 获取工具详情
func (h *AdminHandler) GetTool(c echo.Context) error {
	name := c.Param("name")

	tool, exists := h.toolManager.GetTool(name)
	if !exists {
		return response.NotFound(c, "工具不存在")
	}

	toolInfo := map[string]interface{}{
		"name":        tool.Name(),
		"description": tool.Description(),
		"definition":  tool.Definition(),
	}
	// 新增：返回config字段
	if stats, err := h.toolManager.GetToolStats(tool.Name()); err == nil {
		if stats.Config != nil {
			var configObj interface{}
			_ = json.Unmarshal([]byte(*stats.Config), &configObj)
			toolInfo["config"] = configObj
		} else {
			toolInfo["config"] = nil
		}
	}

	return response.Success(c, toolInfo)
}

// GetToolDefinition 获取工具定义
func (h *AdminHandler) GetToolDefinition(c echo.Context) error {
	name := c.Param("name")

	tool, exists := h.toolManager.GetTool(name)
	if !exists {
		return response.NotFound(c, "工具不存在")
	}

	return response.Success(c, tool.Definition())
}

// ExecuteTool 执行工具
func (h *AdminHandler) ExecuteTool(c echo.Context) error {
	name := c.Param("name")

	var req struct {
		Arguments string `json:"arguments"`
	}

	if err := c.Bind(&req); err != nil {
		return response.BadRequest(c, "无效的请求参数")
	}

	start := time.Now()
	result, err := h.toolManager.ExecuteTool(name, req.Arguments)
	duration := time.Since(start)

	executionData := map[string]interface{}{
		"tool_name":   name,
		"arguments":   req.Arguments,
		"result":      result,
		"success":     err == nil,
		"duration":    duration.Milliseconds(),
		"executed_at": time.Now().Format(time.RFC3339),
	}

	if err != nil {
		executionData["error"] = err.Error()
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{
			"code":    http.StatusInternalServerError,
			"message": "工具执行失败",
			"data":    executionData,
		})
	}

	return response.Success(c, executionData)
}

// UpdateTool 更新工具
func (h *AdminHandler) UpdateTool(c echo.Context) error {
	name := c.Param("name")

	var req UpdateToolRequest
	if err := c.Bind(&req); err != nil {
		return response.BadRequest(c, "invalid request body")
	}

	// Get the existing tool from the database
	toolEntity, err := h.toolManager.GetToolStats(name)
	if err != nil {
		return response.NotFound(c, "tool not found in database")
	}

	// Update fields if provided
	if req.DisplayName != nil {
		toolEntity.DisplayName = *req.DisplayName
	}
	if req.Description != nil {
		toolEntity.Description = *req.Description
	}
	if req.Config != nil {
		// Validate if config is a valid JSON
		if !json.Valid(req.Config) {
			return response.BadRequest(c, "config is not a valid JSON")
		}
		configBytes := datatypes.JSON(req.Config)
		toolEntity.Config = &configBytes
	}

	// Update the tool in the database
	if err := h.toolManager.UpdateTool(toolEntity); err != nil {
		return response.InternalServerError(c, "failed to update tool: "+err.Error())
	}

	// Reload tool configuration to apply changes
	if err := h.toolManager.ReloadToolConfig(name); err != nil {
		// Log warning but don't fail the request - the database update was successful
		// The tool will reload config on next execution anyway
		fmt.Printf("Warning: failed to reload tool config for %s: %v\n", name, err)
	}

	return response.Success(c, map[string]interface{}{"message": "Tool updated successfully"})
}

// UpdateToolStatus 更新工具状态
func (h *AdminHandler) UpdateToolStatus(c echo.Context) error {
	reqDto := new(UpdateToolStatusRequest)
	if err := c.Bind(reqDto); err != nil {
		return response.BadRequest(c, "无效的请求参数")
	}

	name := reqDto.Name
	isEnabled := reqDto.IsEnabled

	// 检查工具是否存在于内存中
	_, exists := h.toolManager.GetTool(name)
	if !exists {
		return response.NotFound(c, "工具不存在于内存中")
	}

	// 尝试在数据库中查找工具（用于调试）
	if stats, err := h.toolManager.GetToolStats(name); err != nil {
		// 如果工具不在数据库中，先注册它
		tool, _ := h.toolManager.GetTool(name)
		h.toolManager.RegisterTool(tool) // 重新注册以确保在数据库中
	} else {
		// 记录当前状态
		_ = stats // 用于调试
	}

	if isEnabled {
		if err := h.toolManager.EnableTool(name); err != nil {
			return response.InternalServerError(c, "启用工具失败: "+err.Error())
		}
	} else {
		if err := h.toolManager.DisableTool(name); err != nil {
			return response.InternalServerError(c, "禁用工具失败: "+err.Error())
		}
	}

	return response.Success(c, nil)
}

// TestToolConnectionRequest 测试工具连接请求
type TestToolConnectionRequest struct {
	Config json.RawMessage `json:"config" validate:"required"`
}

// TestToolConnection 测试工具连接
func (h *AdminHandler) TestToolConnection(c echo.Context) error {
	name := c.Param("name")

	var req TestToolConnectionRequest
	if err := c.Bind(&req); err != nil {
		return response.BadRequest(c, "无效的请求参数")
	}

	// 只支持PostgreSQL工具的连接测试
	if name != "postgresql" {
		return response.BadRequest(c, "该工具不支持连接测试")
	}

	// 解析配置
	var config map[string]interface{}
	if err := json.Unmarshal(req.Config, &config); err != nil {
		return response.BadRequest(c, "配置格式错误")
	}

	// 验证必要的连接参数
	host, ok := config["host"].(string)
	if !ok || host == "" {
		return response.BadRequest(c, "缺少主机地址")
	}

	username, ok := config["username"].(string)
	if !ok || username == "" {
		return response.BadRequest(c, "缺少用户名")
	}

	database, ok := config["database"].(string)
	if !ok || database == "" {
		return response.BadRequest(c, "缺少数据库名")
	}

	password, ok := config["password"].(string)
	if !ok || password == "" {
		return response.BadRequest(c, "缺少密码")
	}

	// 获取其他连接参数，使用默认值
	port := 5432
	if p, ok := config["port"].(float64); ok {
		port = int(p)
	}

	sslMode := "disable"
	if s, ok := config["ssl_mode"].(string); ok && s != "" {
		sslMode = s
	}

	timezone := "UTC"
	if tz, ok := config["timezone"].(string); ok && tz != "" {
		timezone = tz
	}

	// 构建测试连接字符串
	dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s TimeZone=%s",
		host, port, username, password, database, sslMode, timezone)

	// 尝试连接数据库
	testDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		return c.JSON(http.StatusOK, map[string]interface{}{
			"code":    0,
			"message": "连接测试成功",
			"data": map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("连接失败: %v", err),
			},
		})
	}

	// 测试连接
	sqlDB, err := testDB.DB()
	if err != nil {
		return c.JSON(http.StatusOK, map[string]interface{}{
			"code":    0,
			"message": "连接测试成功",
			"data": map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("获取数据库连接失败: %v", err),
			},
		})
	}

	ctx, cancel := context.WithTimeout(c.Request().Context(), 10*time.Second)
	defer cancel()

	if err := sqlDB.PingContext(ctx); err != nil {
		sqlDB.Close()
		return c.JSON(http.StatusOK, map[string]interface{}{
			"code":    0,
			"message": "连接测试成功",
			"data": map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("连接测试失败: %v", err),
			},
		})
	}

	// 关闭测试连接
	sqlDB.Close()

	return response.Success(c, map[string]interface{}{
		"success": true,
		"message": "数据库连接测试成功",
	})
}

// ========== 数据库架构相关方法 ==========

// GetDatabaseSchema 获取数据库架构信息
func (h *AdminHandler) GetDatabaseSchema(c echo.Context) error {
	tables, err := h.repos.GetSchema().GetDatabaseSchema(c.Request().Context())
	if err != nil {
		return response.InternalServerError(c, "获取数据库架构失败: "+err.Error())
	}

	// 转换为响应格式
	var response_tables []TableInfoResponse
	for _, table := range tables {
		var columns []TableColumnResponse
		for _, col := range table.Columns {
			columns = append(columns, TableColumnResponse{
				ColumnName:     col.ColumnName,
				ColumnPosition: col.ColumnPosition,
				DataType:       col.DataType,
				NotNull:        col.NotNull,
				HasDefault:     col.HasDefault,
				DefaultValue:   col.DefaultValue,
				ColumnComment:  col.ColumnComment,
			})
		}

		response_tables = append(response_tables, TableInfoResponse{
			SchemaName:   table.SchemaName,
			TableName:    table.TableName,
			TableComment: table.TableComment,
			Columns:      columns,
		})
	}

	return response.Success(c, SchemaResponse{
		Tables: response_tables,
	})
}

// GetTableList 获取表列表
func (h *AdminHandler) GetTableList(c echo.Context) error {
	tables, err := h.repos.GetSchema().GetTableList(c.Request().Context())
	if err != nil {
		return response.InternalServerError(c, "获取表列表失败: "+err.Error())
	}

	// 转换为响应格式
	var basic_tables []TableBasicInfo
	for _, table := range tables {
		basic_tables = append(basic_tables, TableBasicInfo{
			SchemaName:   table.SchemaName,
			TableName:    table.TableName,
			TableComment: table.TableComment,
		})
	}

	return response.Success(c, TableListResponse{
		Tables: basic_tables,
	})
}

// GetTableSchema 获取指定表的架构信息
func (h *AdminHandler) GetTableSchema(c echo.Context) error {
	schemaName := c.QueryParam("schema")
	tableName := c.QueryParam("table")

	if schemaName == "" || tableName == "" {
		return response.BadRequest(c, "缺少必要参数: schema 和 table")
	}

	table, err := h.repos.GetSchema().GetTableSchema(c.Request().Context(), schemaName, tableName)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return response.NotFound(c, "表不存在")
		}
		return response.InternalServerError(c, "获取表架构失败: "+err.Error())
	}

	// 转换为响应格式
	var columns []TableColumnResponse
	for _, col := range table.Columns {
		columns = append(columns, TableColumnResponse{
			ColumnName:     col.ColumnName,
			ColumnPosition: col.ColumnPosition,
			DataType:       col.DataType,
			NotNull:        col.NotNull,
			HasDefault:     col.HasDefault,
			DefaultValue:   col.DefaultValue,
			ColumnComment:  col.ColumnComment,
		})
	}

	tableResponse := TableInfoResponse{
		SchemaName:   table.SchemaName,
		TableName:    table.TableName,
		TableComment: table.TableComment,
		Columns:      columns,
	}

	return response.Success(c, tableResponse)
}

// ========== 工具数据库架构相关方法 ==========

// GetToolDatabaseSchema 获取工具数据库架构（JSON格式）
func (h *AdminHandler) GetToolDatabaseSchema(c echo.Context) error {
	toolName := c.Param("tool_name")
	if toolName == "" {
		return response.BadRequest(c, "缺少工具名称参数")
	}

	// 目前只支持 PostgreSQL 工具
	if toolName != "postgresql" {
		return response.BadRequest(c, "仅支持PostgreSQL工具的架构查看")
	}

	// 获取工具配置
	toolStats, err := h.toolManager.GetToolStats(toolName)
	if err != nil {
		return response.NotFound(c, "工具不存在")
	}

	if !toolStats.IsEnabled {
		return response.BadRequest(c, "工具已禁用")
	}

	if toolStats.Config == nil {
		return response.BadRequest(c, "工具配置为空，请先配置数据库连接信息")
	}

	// 解析工具配置
	var config map[string]interface{}
	if err := json.Unmarshal([]byte(*toolStats.Config), &config); err != nil {
		return response.BadRequest(c, "工具配置格式错误")
	}

	// 验证必要的连接参数
	host, ok := config["host"].(string)
	if !ok || host == "" {
		return response.BadRequest(c, "配置中缺少主机地址")
	}

	username, ok := config["username"].(string)
	if !ok || username == "" {
		return response.BadRequest(c, "配置中缺少用户名")
	}

	database, ok := config["database"].(string)
	if !ok || database == "" {
		return response.BadRequest(c, "配置中缺少数据库名")
	}

	password, ok := config["password"].(string)
	if !ok || password == "" {
		return response.BadRequest(c, "配置中缺少密码")
	}

	// 获取其他连接参数，使用默认值
	port := 5432
	if p, ok := config["port"].(float64); ok {
		port = int(p)
	}

	sslMode := "disable"
	if s, ok := config["ssl_mode"].(string); ok && s != "" {
		sslMode = s
	}

	timezone := "UTC"
	if tz, ok := config["timezone"].(string); ok && tz != "" {
		timezone = tz
	}

	// 创建临时的ToolDBConnection对象用于获取架构
	tempConnection := &entity.ToolDBConnection{
		Name:     fmt.Sprintf("temp-%s", toolName),
		Host:     host,
		Port:     port,
		Username: username,
		Password: password,
		DBName:   database,
		SSLMode:  sslMode,
		Timezone: timezone,
	}

	// 获取工具数据库架构
	tables, err := h.repos.GetSchema().GetToolDatabaseSchema(c.Request().Context(), tempConnection)
	if err != nil {
		return response.InternalServerError(c, "获取工具数据库架构失败: "+err.Error())
	}

	// 构建JSON响应，包含连接信息和架构信息
	schemaResponse := map[string]interface{}{
		"tool_info": map[string]interface{}{
			"name":         toolStats.Name,
			"display_name": toolStats.DisplayName,
			"description":  toolStats.Description,
		},
		"connection_info": map[string]interface{}{
			"host":     host,
			"port":     port,
			"db_name":  database,
			"username": username,
			"timezone": timezone,
		},
		"database_schema": map[string]interface{}{
			"total_tables": len(tables),
			"total_columns": func() int {
				count := 0
				for _, table := range tables {
					count += len(table.Columns)
				}
				return count
			}(),
			"schemas": func() map[string]interface{} {
				schemaMap := make(map[string]interface{})
				for _, table := range tables {
					if _, exists := schemaMap[table.SchemaName]; !exists {
						schemaMap[table.SchemaName] = map[string]interface{}{
							"tables": []interface{}{},
						}
					}

					schemaInfo := schemaMap[table.SchemaName].(map[string]interface{})

					tableInfo := map[string]interface{}{
						"name":    table.TableName,
						"comment": table.TableComment,
						"columns": func() []interface{} {
							columns := make([]interface{}, len(table.Columns))
							for i, col := range table.Columns {
								columns[i] = map[string]interface{}{
									"name":          col.ColumnName,
									"position":      col.ColumnPosition,
									"data_type":     col.DataType,
									"not_null":      col.NotNull,
									"has_default":   col.HasDefault,
									"default_value": col.DefaultValue,
									"comment":       col.ColumnComment,
								}
							}
							return columns
						}(),
					}

					schemaInfo["tables"] = append(schemaInfo["tables"].([]interface{}), tableInfo)
					schemaMap[table.SchemaName] = schemaInfo
				}
				return schemaMap
			}(),
		},
		"generated_at": time.Now().Format(time.RFC3339),
	}

	return response.Success(c, schemaResponse)
}
